#--
#   Television Episode Renamer
#   - Initial Milestone: April 2nd, 08
#       - Find URL from epguides.com
#       - filenames to rename_list.csv
#   - Internal Milestone 1: April 2nd, 08 to April 5th, 08
#       - construct new name based on Template
#       - correctly interact with rename_list, make batch/sh/etc and better
#   - Internal Milestone 2: April 5th, 08 to April 6th, 08
#       - search an epguides.txt file and html page and fill out ep title
#   - Internal Milestone 3: April 6th, 08 - April 8th, 08
#       - option to walk directory structure from given location
#       - optparse add and support
#   - Internal Milestone 4: April 8th, 08 to April 10th, 08
#       - optionize more assumptions /
#       - handle showname/Season # /
#       - more judicious printing - eg: handle folder as a batch? /
#       - seperate verbose and debug print /
#       - decide "normal" printouts /
#       - reduce O(n) where obvious /
#       - interactive/batch mode /
#   - Internal Mileston 5: April 10th, 08 - April 16th, 08
#       - tv.com support, website (/), cache (/) and text file (/)
#       - splitting up a complete series folder, when numbered in air order /
#       - support .html versions as file /
#   - Eventual Goals
#       - Nice to Have
#           - create html page with each file's link to recap
#               + page has link to dvd/show site image, saved to dir as folder.jpg
#           - implement caching (/), saving source site to plain text
#           - preferences file
#           - add new sources
#           - pull the recap from epguides/other guides (twop) to dir
#           - interaction with TED/miro/other open source players
#       - Epguides Support
#           - investigate consequence of assuming dot{28}
#       - TV.com support
#           - use the all episodes summary page to rename a full run
#       - Non-standard numbering
#           - double episode numbers with two titles
#           - clip shows, miniseries
#           - British conventions
#               + Series "names" as in Blackadder Goes Fourth
#       - Interaction
#           - create a simple breakpoint function for debug
#       - Files/Folders organization issues
#           - get/confirm show name from the filename
#           - for complete series in one folder, split it
#           - fully handle folder schemes that aren't too weird
#           - Option to move files into new folders
#
#   Rob Dennis - Lurchington Q. Delacroix ESQ. and man about town
#
#   This script is inspired and is thanks to:
#   -   Rob Meerman's tvrenamer perl script
#           http://www.robmeerman.co.uk/coding/file_renamer
#   -   Softpointer's Tag&Rename
#           http://www.softpointer.com/tr
#   
#--

import os,re,glob,time,sys,string,shutil,urllib2
from string import Template

from optparse import OptionParser

unparsedFiles = []
unfoundWebsites = []

osRenameCommand = "mv"
undoBatchName = "undoBatch.sh"
nameBatchName = "nameBatch.sh"
batchHeaderString = r"#!/bin/bash"

parser = OptionParser(version="%prog - Internal Mileston 5 - Start: April 10th, 2008")

parser.add_option("--makeUndoBatchFile",dest="undoBatchFlag",action="store_true",
                  help="enable creation of naming batch file",default=False)

parser.add_option("--makeNamingBatchFile",dest="nameBatchFlag",action="store_true",
                  help="enable creation of undo batch file",default=False)

parser.add_option("--writeCacheToFile",dest="writeCacheToFileFlag",action="store_true",
                  help="writes webpage cache to text file in dir",default=True)

parser.add_option("--quashBatchEntries",dest="quashBatchEntriesFlag",action="store_true",
                  help="always overwrite batch file",default=False)

parser.add_option("--pretend",dest="pretendFlag",action="store_true",
                  help="do not make any changes",default=True)

parser.add_option("--assumeGroupedNum",dest="assumeGroupedNumFlag",action="store_true",
                  help="treats fields like 1005 as both season and episode number",default=True)

parser.add_option("--guessMultipart",dest="guessMultipartFlag",action="store_true",
                  help="will not read Part 1 in title as episode number 1",default=True)

parser.add_option("--assumeFullRun",dest="assumeFullRunFlag",action="store_true",
                  help="for episodes numbered with the overall show order",default=True)

parser.add_option("--splitFullRun",dest="splitFullRunFlag",action="store_true",
                  help="split full run into season and episode",default=True)

##parser.add_option("--guessShowNameFlag",dest="guessShowFromNameFlag",action="store_true",
##                  help="attempts to infer show name from fileName (unwieldy)",default=True)

parser.add_option("--groupNumSplit",dest="groupNumSplit",metavar="NUM",
                  help="when handling group numbers, split after NUM places [default: %default]",default=4)

parser.add_option("--episodePadding",dest="episodePadding",metavar="NUM",
                  help="pads episode number to NUM places [default: %default]",default=2)

parser.add_option("--seasonPadding",dest="seasonPadding",metavar="NUM",
                  help="pads season number to NUM places [default: %default]",default=2)

parser.add_option("--splitEpisodeChar",dest="splitEpisodeChar",metavar="CHAR",
                  help="Detects numbers split by CHAR as multi-episodic [default: %default]",default="-")

parser.add_option("--useUnixNaming",dest="useUnixNamingFlag",action="store_true",
                  help="replaces whitespace with '_'",default=False)

parser.add_option("--allowPartialInfo",dest="allowPartialInfoFlag",action="store_true",
                  help="All",default=False)

parser.add_option("--recursiveRename",dest="recursiveRenameFlag",action="store_true",
                  help="recursively rename files in all subdirectory",default=True)

parser.add_option("--debug",dest="debugFlag",action="store_true",
                  help="print extra debug output",default=True)

parser.add_option("--verbose",dest="verboseFlag",action="store_true",
                  help="print verbose output",default=True)

parser.add_option("--quiet",dest="quietFlag",action="store_true",
                  help="print extra debug output",default=False)

parser.add_option("--topLevel",dest="topLevelDir",metavar="PATH",
                  help="top level rename hierarchy [default: %default]",default=os.getcwd()+r"/Volumes/INCOMING_TV/DuckTales")

parser.add_option("--unattended",dest="unattendedFlag",action="store_true",
                  help="do not prompt for input",default=True)

parser.add_option("--renameString",dest="renameString",metavar="STRING",
                  help="rename filename to formatted STRING [default: %default]",
                  default=r"${showName} - S${seasonNum}E${episodeNum} - ${episodeTitle}")

originalCwd=os.getcwd()

tvComTxt= {"name":"TV.com textfile","isFile":True,"isSite":False,"filename":"tvcom.txt","syntax":"tvComTxt"}
tvComCacheHTML = {"name":"TV.com Webpage Cache","isFile":True,"isSite":False,"filename":"tvcom.html","syntax":"tvComHTML"}
tvComWebHTML = {"name":"TV.com Webpage","isFile":False,"isSite":True,"URL":r"http://www.tv.com/search.php?type=11&stype=program&qs=","syntax":"tvComHTML","cacheFile":tvComCacheHTML}
epguidesTxt= {"name":"Epguides textfile","isFile":True,"isSite":False,"filename":"epguides.txt","syntax":"epguidesTxt"}
epguidesCacheHTML= {"name":"Epguides Webpage Cache","isFile":True,"isSite":False,"filename":"epguides.html","syntax":"epguidesHTML"}
epguidesWebHTML= {"name":"Epguides Webpage","isFile":False,"isSite":True,"URL":r"http://www.epguides.com/","syntax":"epguidesHTML","cacheFile":epguidesCacheHTML}

(opt,arg) = parser.parse_args()

informationSources= [epguidesTxt,epguidesCacheHTML,epguidesWebHTML,tvComTxt,tvComCacheHTML,tvComWebHTML]

if opt.useUnixNamingFlag:
    whitespaceToUnderscore = string.maketrans(" ","_")

def dPrnt(string,flag=opt.debugFlag,left="<dPrnt-:",right="->"):
    if flag and (opt.verboseFlag and not opt.quietFlag):
        print left+str(string)+right

def vPrnt(string,flag=opt.verboseFlag,left="{vPrnt-:",right="-}"):
    if flag and not opt.quietFlag:
        print left+str(string)+right

def qPrnt(string,flag=opt.quietFlag,left="",right=""):
    if not flag:
        print left+str(string)+right        

def checkRegexList(regexList,label=""):
    for x in range(len(regexList)):
        if regexList[x]:
            returnVal = regexList[x].group(0).strip()
            dPrnt("%sRE%i: %s" %(label,x+1,returnVal))
            return returnVal
    dPrnt("%s not parsed in string"%label)
    return "UNK"

def renameFileList(inList):
    unRenamedLines = []
    count = 0
    
    dPrnt("cwd: %s" % os.getcwd())
    parentDir=os.path.split(os.getcwd())[1].strip()
    parentOfParentDir=os.path.split(os.path.split(os.getcwd())[0])[1].strip()
    dPrnt("Parent of Parent Dir: %s" % parentOfParentDir)
    dPrnt("Parent Dir: %s" % parentDir)

    newNames = reshapeNames(inList,parentDir,parentOfParentDir)

    qPrnt("Attempting to make the following changes")
    qPrnt("----------------------------------------")
    for x in range(len(inList)):
        if newNames[x]!=inList[x]:
            qPrnt("%s %s %s" %(osRenameCommand,inList[x],newNames[x]))
            count = count + 1
        else:
            unRenamedLines.append("%s"%inList[x])
    if count == 0:
        qPrnt("no files changed")
        qPrnt("----------------------------------------")
        return None

    qPrnt("----------------------------------------")

    if opt.verboseFlag:
        vPrnt("renaming %i files"%count)

        
    if not opt.quietFlag and len(unRenamedLines):
        print "Unnamed files:|"
        print "--------------+"
        for untouchedFile in unRenamedLines:
           print "\t- %s" % untouchedFile

    if (opt.undoBatchFlag):
        makeNamingBatchFile(undoBatchName,osRenameCommand,row,inList)
    if (opt.nameBatchFlag):
        makeNamingBatchFile(nameBatchName,osRenameCommand,row,inList)


def makeNamingBatchFile(fileName,command,source,dest):
    vPrnt("creating batch file")
    if opt.quashBatchEntriesFlag:
        vPrnt("overwriting current batch")
    if len(source) != len(dest):
        qPrnt("mismatched rename lists batch create failed!")
    else:
        sourceNot=[]
        destNot=[]
        if os.path.exists(fileName):
            inF=open(fileName,"rb")

            if not opt.quashBatchEntriesFlag:
                modeString="ab"
                for line in inF.readlines():
                    if len(line)>1:
                        if line[0] != "#":
                            lineS=line.split()[1:]
                            if len(lineS)>1 and (lineS[1] in dest):
                                dPrnt(lineS[1]+"matched, dropped from file")
                                x=dest.index(lineS[1])
                                destNot.append(dest[x])
                                sourceNot.append(source[x])
                inF.close()
                
            else:
                modeString="wb"
        elif not pretendMoveFlag:
            modeString="wb"
            os.system("touch %s" %fileName)


        if not pretendMoveFlag:
            outF=open(fileName,modeString)

            if modeString=="wb":
                outF.write(batchHeaderString+"\n")            
        
        for x in range(len(source)):
            if not pretendMoveFlag:
                if source[x] not in sourceNot and dest[x] not in destNot:
                    if source[x]!=dest[x]:
                        outF.write("%s %s %s\n" %(command,source[x],dest[x]))
                    else:
                        dPrnt("batch source and dest match for %s, dropping line" % source[x])
        if not pretendMoveFlag:
            outF.close()
            

def reshapeNames(oldNameList,parentDir,parentOfParentDir,renameString=opt.renameString):
    dPrnt("in reshapeNames")
    
    nameTemplate=Template(renameString)
    newNameList=[]

    for oldName in oldNameList:
        show,season,episode,title=searchInfo(oldName,parentDir,parentOfParentDir)
        if not opt.allowPartialInfoFlag:
            if show=="UNK" or season=="UNK" or episode=="UNK" or title=="UNK":
                vPrnt("returning old name due to undefined information")
                unparsedFiles.append("%s/%s/%s"%(parentOfParentDir,parentDir,oldName))
                newName=oldName
            else:
                extension=oldName[oldName.rfind("."):]
                newName=nameTemplate.substitute(showName=str(show),seasonNum=str(season),
                                            episodeNum=str(episode),
                                            episodeTitle=str(title)+extension)

                
        else:
            extension=oldName[oldName.rfind("."):]
            newName=nameTemplate.substitute(showName=str(show),seasonNum=str(season),
                                            episodeNum=str(episode),
                                            episodeTitle=str(title)+extension)
            
        if opt.useUnixNamingFlag:
            newName=newName.translate(whitespaceToUnderscore)
            
        newNameList.append(newName)
        
    return newNameList

def searchInfo(fileN,parentDir,parentOfParentDir):
    dPrnt("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
    dPrnt("in searchInfo")
    vPrnt("+------------------------")
    vPrnt("| - fileN: %s" % fileN)
    vPrnt("+------------------------")
    
#- Getting tv show name from folder
    
    parentDir=os.path.split(os.getcwd())[1].strip()
    parentOfParentDir=os.path.split(os.path.split(os.getcwd())[0])[1].strip()

    dPrnt("%s -> "%parentDir)
    parentDir=re.sub(r"[^A-Za-z0-9]"," ",parentDir)
    dPrnt("-> %s "%parentDir)

    shownameRegexList = []
    #shownameRE1
    shownameRegexList.append(re.search(r".*(?=(Season|Series))",parentDir,re.IGNORECASE))
    #shownameRE2
    shownameRegexList.append(re.search(r".*?(?=s\d+)",parentDir,re.IGNORECASE))
    #shownameRE3
    shownameRegexList.append(re.search(r"(\w|\S)*?(?=(\d))",parentDir,re.IGNORECASE))
    #shownameRE4
    shownameRegexList.append(re.search(r".*",parentDir,re.IGNORECASE))

    showname = checkRegexList(shownameRegexList,"showname")

    if len(showname)==0:
        dPrnt("using parent of parent directory as show name")
        showname=parentOfParentDir

##    if opt.guessShowFromNameFlag:
##        vPrnt("| checking showname in filename")
##        vPrnt("+ %s" % fileN)        
##        vPrnt("re1: %s" % re.search(r"[A-Z]*(?=[\ _\.])",fileN,re.IGNORECASE).group())
##        vPrnt("re2: %s" % re.search(r"(?<=[\. _]).*?(?=[A-Z\ \._][0-9])",fileN,re.IGNORECASE).group())
##        vPrnt("---")
        
        
#- Getting season number from filename

    seasonRet="UNK"
    episodeRet="UNK"

    seasonRegexList=[]

    #seasonRE1
    seasonRegexList.append(re.search(r"^[0-9]+",fileN,re.I))
    #seasonRE2
    seasonRegexList.append(re.search(r"(?<=(Season)[\ \._])[0-9]*",fileN,re.I))
    #seasonRE3
    seasonRegexList.append(re.search(r"(?<=[\ _xs\.])[0-9]+",parentDir,re.I))
    #seasonRE4
    seasonRegexList.append(re.search(r"(?<=[\ _xs\.])[0-9]+",fileN,re.I))
    
    seasonRet=checkRegexList(seasonRegexList,"season")

    if seasonRet!="UNK":
        seasonIndex=fileN.find(seasonRet)+len(seasonRet)
    else:
        seasonIndex=0
                  
    if seasonRet != "UNK" and opt.assumeGroupedNumFlag:
        if len(seasonRet)>opt.groupNumSplit:
            episodeRet=seasonRet[-opt.groupNumSplit:]
            seasonRet=seasonRet[:-opt.groupNumSplit]
            dPrnt("splitting value into s:%s and leaving:%s "%(seasonRet,fileN[seasonIndex:]))
        else:
            dPrnt("---")
            dPrnt("index set at: %d, leaving: %s "%(seasonIndex,fileN[seasonIndex:]))
            dPrnt("---")
                
            
#- Getting episode number from filename

    if episodeRet == "UNK":
        episodeRegexList = []

        episodeRegexList.append(re.search(r"(?<=e])[0-9]+",fileN,re.I))
        episodeRegexList.append(re.search(r"(?<=[\ _xe\.])[0-9]+",fileN[seasonIndex:],re.I))
        episodeRegexList.append(re.search(r"[0-9]+",fileN[seasonIndex:],re.I))
        
        episodeRet=checkRegexList(episodeRegexList,"episode")

        dPrnt(re.findall(r"(?<=\D)[0-9]+(?=\D)",fileN[seasonIndex:]))


    if episodeRet!="UNK" and opt.guessMultipartFlag and len(re.findall(r"(?<=\D)[0-9]+(?=\D)",fileN[seasonIndex:]))>0:
        dPrnt("check for multipart episode read as show number")
        dPrnt("originally thought episodeRet was: %s"%episodeRet)
        multipartCheckList=[r"(part|p|pt)[\. 0]*%s"%str(int(episodeRet[:opt.episodePadding])),
                                r"[{\[].*%s.*[}\]]"%str(int(episodeRet[:opt.episodePadding]))]

        for checkRegex in multipartCheckList:
            if re.search(checkRegex,fileN,re.IGNORECASE):
                dPrnt("found %s in filename, assuming multipart episode"%re.search(checkRegex,fileN,re.IGNORECASE).group(0))
                episodeRet="UNK"
                
    if episodeRet == "UNK" and seasonRet != "UNK" and re.search(r"[0-9]+",fileN,re.I):
        dPrnt("assuming only number in filename is episode")

        dPrnt("using folder name to find season number")
        episodeRet=seasonRet

        seasonRegexList = []
        seasonRegexList.append(re.search(r"(?<=[\ _xs\.])[0-9]+",parentDir,re.I))

        seasonRet=checkRegexList(seasonRegexList,"seasonRedo")

#- Getting the episde title from a source
    if episodeRet.isdigit() and showname != "UNK":
        for source in informationSources:
            if opt.splitFullRunFlag:
                title,seasonRet,episodeRet=getTitleFromSource(source,showname,seasonRet,episodeRet)
            else:
                title=getTitleFromSource(source,showname,seasonRet,episodeRet)
                
            if title!="UNK":
                break
    else:
        title="UNK"

    if seasonRet.isdigit():
        seasonRet=seasonRet.zfill(opt.seasonPadding)
    if episodeRet.isdigit():
        episodeRet=episodeRet.zfill(opt.episodePadding)
        
    vPrnt("+------------------------")
    vPrnt("| - [showname]: %s [seasonRet]: %s [episodeRet]: %s [title]: %s" %(showname,seasonRet,episodeRet,title))
    vPrnt("+------------------------")

    return showname,seasonRet,episodeRet,title
        
def getTitleFromSource(source,showname,season,episode):
# + --------------
# - Getting source information to sourceDump
# + --------------

    dPrnt(("getting title from %s")%source["name"])
    newEpisode=episode
    newSeason=season


    if source["isSite"]:
        dPrnt("which is at %s"%source["URL"])
        if source["syntax"]=="epguidesHTML":
            norm = string.maketrans("","")
            searchTerm=showname.translate(norm,string.whitespace+"'")
            if re.match("The",searchTerm,re.I):
                searchTerm=searchTerm[3:]

            searchTerm=re.sub("&","And",searchTerm)
            pullPage=source["URL"]+searchTerm
            vPrnt("searching %s"%pullPage)

        if source["syntax"]=="tvComHTML":
            if season=="UNK":
                dPrnt("unknown season, returning unknown title")
                return "UNK",season,episode
     
            searchTerm=re.sub(" ","%20",showname)
            splashPage=source["URL"]+searchTerm

            if source.has_key(splashPage):
                dPrnt("loaded %s from cache"%splashPage)
                splashPageDump = source[splashPage]
            else:
                dPrnt("caching %s"%splashPage)
                try:
                    splashPageDump = urllib2.urlopen(splashPage).read()
                except:
                    dPrnt("no page found, continuing search")
                    source[splashPage]=None
                    unfoundWebsites.append("---\n%s\n%s\n---\n" %(os.getcwd(),splashPage))
                    return "UNK",season,episode
                
                source[splashPage]=splashPageDump

            if not splashPageDump:
                dPrnt("cached results show unknown show name")
                return "UNK",season,episode

            shownameDash=re.sub(" ","-",showname)
            tvComNumberMatch=re.search(r"(?<=(http://www.tv.com/%s/show/))[0-9]*(?=(/summary.html?))"%shownameDash,splashPageDump,re.IGNORECASE+re.MULTILINE)
            if tvComNumberMatch:
                dPrnt("splashpage finds tvCom number: %s"%tvComNumberMatch.group(0))
                tvComNumber=tvComNumberMatch.group(0)
            else:
                dPrnt("search not yielding results for %s at tv.com"%showname)
                return "UNK",season,episode

            if season.isdigit():
                pullPage=r"http://www.tv.com/%s/show/%s/episode.html?season=%s&tag=season_dropdown;dropdown;0"%(shownameDash,tvComNumber,str(int(season)))
            else:
                dPrnt("non numerical season, returning unknown title")
                return "UNK",season,episode
 
        if source.has_key(pullPage):
            sourceDump=source[pullPage]
            dPrnt("%s information loaded from %s" %(searchTerm,source["syntax"]))
        else:
            try:
                sourceDump=urllib2.urlopen(pullPage).read()
                
            except:
                dPrnt("no page found, continuing search")
                source[pullPage]=None

                unfoundWebsites.append("---\n%s\n%s\n---\n" %(os.getcwd(),pullPage))
                
                return "UNK",season,episode
            dPrnt("%s information saved to %s" %(showname,source["syntax"]))
            source[pullPage]=sourceDump

            if opt.writeCacheToFileFlag:
                cacheFilename=source["cacheFile"]["filename"]
                dPrnt("Writing cachefile to %s"%cacheFilename)
                outF=open(cacheFilename,"wb")
                outF.write(sourceDump)
                outF.close()

        if not sourceDump:
            dPrnt("cached results show unknown show name")
            return "UNK",season,episode

    elif source["isFile"]:
        vPrnt("which is %s"%source["filename"])
        if os.path.exists(source["filename"]):
            sourceDump=open(source["filename"],"rb").read()
        else:
            dPrnt("%s does not exist"%source["filename"])
            return "UNK",season,episode

    else:
        dPrnt("unknown source type")
        return "UNK",season,episode

# + --------------
# - Now operating on sourcePage by constructing regular expressions
# + --------------

    dPrnt("searching for %s in sourcePage"%showname)
    dPrnt("Using [showname]: %s [season]: %s [episode]: %s" %(showname,season,episode))

    if season == "UNK" and episode != "UNK":
        if opt.assumeFullRunFlag:   #full run syntax
            dPrnt("attempting to use broadcast order")
            # epguides.com copy and paste format
            if source["syntax"]=="epguidesTxt":
                lineTemplate=Template(r"(?<=${episodeT}\.).*")
                lineTemplate=lineTemplate.substitute(episodeT=str(int(episode)).rjust(4))


                dPrnt("lineTemplate: %s"%lineTemplate)

                lineRE=re.compile(lineTemplate,re.IGNORECASE+re.MULTILINE)

                lineMatch=re.search(lineRE,sourceDump)

                if lineMatch:
                    dPrnt("found broadcast number %s"%str(episode))

                    if opt.splitFullRunFlag:
                        dPrnt("attempting to discern season-episode split")
                        line=lineMatch.group(0)
                        dPrnt(line)
                        newSeason=re.search(r"[0-9]*(?=-)",line).group(0)
                        newEpisode=re.search(r"(?<=-)[ ]?[0-9]*",line).group(0)
                        dPrnt("guessing info as season:%s episode:%s"%(newSeason,newEpisode))
                        
                    sourceDump=lineMatch.group(0)
                    titleRE=re.compile(r"(?<=[A-Za-z]{3} [0-9]{2} ).*")
                else:
                    dPrnt("step broadcast 1: title not parsed from %s"%source["name"])
                    return "UNK",season,episode
                    

            else:
                dPrnt("invalid braodcast run source syntax,%s specified by %s"%(source["syntax"],source["name"]))
                return "UNK",season,episode
            
        else:
            dPrnt("returning unknown title due to unknown season")
            return "UNK",season,episode
    else:   #non-full run syntax
        # epguides.com html format
        if source["syntax"]=="epguidesHTML":
            searchTemplate=Template(r"(?<=${seasonT}-${episodeT}.{28}).*")
            searchTemplate=searchTemplate.substitute(seasonT=str(int(season)).rjust(2),episodeT=str(int(episode)).rjust(2))
            lineRE=re.compile(searchTemplate,re.IGNORECASE+re.MULTILINE)
            
            lineMatch=lineRE.search(sourceDump)

            if lineMatch:
                sourceDump=lineMatch.group(0)
                titleRE=re.compile(r"(?<=>).*?(?=<)")
            else:
                dPrnt("step 1: title not parsed from %s"%source["name"])
                return "UNK",season,episode

            
        # epguides.com copy and paste format
        elif source["syntax"]=="epguidesTxt":
            sval=str(int(season)).rjust(2)
            epval=str(int(episode)).rjust(2)
            searchTemplate=Template(r"(?<=${seasonT}-${episodeT}.{28}).*")
            searchTemplate=searchTemplate.substitute(seasonT=sval,episodeT=epval)
            titleRE=re.compile(searchTemplate,re.IGNORECASE+re.MULTILINE)

        elif source["syntax"]=="tvComHTML":
            sourceDumpL = re.findall(r"<h1 class=\"f-18 f-666\">\s*?\d+.*?</a>",sourceDump,re.DOTALL+re.IGNORECASE+re.MULTILINE)
            if int(episode)-1 < len(sourceDumpL):
                sourceDump=sourceDumpL[int(episode)-1]
            else:
                dPrnt("no results found in sourceDumpL")
                return "UNK",season,episode
                
##            sourceDump = re.search(r"<td class=\"first.*?>\s*?\d*\s+?</td>.*?summary\.html\?.*?</a>",sourceDump,re.DOTALL+re.IGNORECASE).group(int(episode)-1)
            titleRE=re.compile(r"(?<=>).*?(?=<)")

        elif source["syntax"]=="tvComTxt":
            sourceDump = re.findall(r"^(?:(?:[0-9]+?\.)|Pilot|Special).*?(?=Community Score)",sourceDump,re.DOTALL+re.MULTILINE+re.IGNORECASE)[int(episode)-1]
##            sourceDump = re.search(r"^(?:(?:[0-9]+?\.)|Pilot|Special).*?(?=Community Score)",sourceDump,re.DOTALL+re.MULTILINE+re.IGNORECASE).group(int(episode)-1)
            print sourceDump
##            print sourceDump
##            dPrnt("sourceDump: %s"%sourceDump)
            sourceDump=re.sub("Pilot|Special",str(episode)+".",sourceDump)
            titleRE=re.compile(r"(?<=\.).*")
               
        else:
            dPrnt("invalid source syntax,%s specified by %s"%(source["syntax"],source["name"]))
            return "UNK",season,episode

# + --------------
# - Now operating on sourcePage by evaluating regular expression
# + --------------

    titleMatch = titleRE.search(sourceDump)
    
    if titleMatch:
        if opt.splitFullRunFlag:
            return titleMatch.group(0).strip(),newSeason.strip(),newEpisode.strip()
        else:
            return titleMatch.group(0)
    else:
        dPrnt("title not parsed from %s"%source["name"])
        return "UNK",season,episode



def main():
    startTime=time.time()
    
    fileTypes = re.compile(r'.*(\.avi|mkv|\.mpg|\.rm|\.flv)$',re.IGNORECASE)

    os.chdir(opt.topLevelDir)
    
    for root,dirs,fileNameList in os.walk(opt.topLevelDir):
        qPrnt("checking %s" %root)
        os.chdir(root)
        
        if len(fileNameList)>0:
            newFileNameList = []

            for fileN in fileNameList:
                if fileTypes.match(fileN):
                    newFileNameList.append(fileN)

            listLength=len(newFileNameList)

            vPrnt("Attempting to rename %s files" % listLength)

            if listLength>0:
                renameFileList(newFileNameList)

                if not opt.unattendedFlag:
                    prompt=raw_input("continue? (y/n): ")
                
                    if not re.match(prompt[0],"y",re.IGNORECASE):
                        break            
            else:
                vPrnt("no usable files found in %s" % root)

            qPrnt(time.time()-startTime)
            qPrnt("---")

main()
os.chdir(originalCwd)
##if not opt.quietFlag:
##    qPrnt("--------------------")
##    qPrnt("unParsedFiles")
##    for x in unparsedFiles:
##        print x
##    qPrnt("--------------------")
##    qPrnt("unfoundWebsites")
##    for x in unfoundWebsites:
##        print x
##    qPrnt("--------------------")

print "--------------------"
print "unParsedFiles"
for x in unparsedFiles:
    print x
print "--------------------"
print "unfoundWebsite"
for x in unfoundWebsites:
    print x
print "--------------------"

